/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * config.c
 *
 * Copyright (C) 2008, 2009 Lingtao Pan
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, 
 * Boston, MA 02111-1307, USA.
 */


#include "gftp.h"

static GKeyFile* key_file;


void
gftp_config_register_items (gftp_config_item *items)
{
    gftp_config_item *item = items;
    GError *error = NULL;
    gboolean has_key;
    gdouble value;

    while (item->group != NULL) {
        has_key = g_key_file_has_key (key_file, item->group, item->key, &error);
        if (error != NULL) {
            if (error->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND
                && error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) 
            {
                g_error ("gftp_config_register_items fails when calling "
                         "has_key (): %s", error->message);
                break;
            }
        }

        if (has_key) {
            item++;
            continue;
        }

        switch (item->type) {
        case GFTP_CONFIG_TYPE_STRING:
            g_key_file_set_string (key_file, item->group, item->key, 
                                   (char *) item->value);
            break;
        case GFTP_CONFIG_TYPE_STRING_LIST:
            g_key_file_set_string (key_file, item->group, item->key, 
                                   (char *) item->value);
            break;
        case  GFTP_CONFIG_TYPE_INT:
            g_key_file_set_integer (key_file, item->group, item->key, 
                                    (int) item->value);
            break;
        case GFTP_CONFIG_TYPE_BOOLEAN:
            g_key_file_set_boolean (key_file, item->group, item->key, 
                                    (gboolean) item->value);
            break;
        case GFTP_CONFIG_TYPE_DOUBLE:
            value = g_strtod (item->value, NULL);
            g_key_file_set_double (key_file, item->group, item->key, 
                                   value);
            break;
        default:
            g_error ("gftp_config_register_items: unknown item type %d", 
                     item->type);
            return;
        }

        g_key_file_set_comment (key_file, item->group, item->key, 
                                (const char *) item->comment, NULL);

        item++;
    }
}


int
gftp_config_load ()
{
    GError *error = NULL;
    gchar *tempstr, *temp1str;
    int i;

    key_file = g_key_file_new ();

    if ((tempstr = gftp_expand_path (CONFIG_FILE2)) == NULL)
    {
        fprintf (stderr, _("gFTP2 Error: Bad config file name %s\n"), CONFIG_FILE2);
        exit (EXIT_FAILURE);
    }

    if (access (tempstr, F_OK) == -1) {
        temp1str = gftp_expand_path (BASE_CONF_DIR);
        if (access (temp1str, F_OK) == -1) {
            if (mkdir (temp1str, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
                fprintf (stderr, _("gFTP Error: Could not make directory %s: %s\n"),
                        temp1str, g_strerror (errno));
                exit (EXIT_FAILURE);
            }
        }
        g_free (temp1str);

        temp1str = g_strdup_printf ("%s/gftprc2.sample", PACKAGE_DATA_DIR);

        if (access (temp1str, F_OK) == -1) {
            fprintf (stderr, _("gftp2 Error: Cannot find sample config file %s\n"),
                    temp1str);
            fprintf (stderr, _("Did you do a make install?\n"));
            exit (EXIT_FAILURE); 
        }

        copyfile (temp1str, tempstr);
        g_free (temp1str);
    }
    
    if (!g_key_file_load_from_file (key_file, tempstr,
                                    G_KEY_FILE_KEEP_COMMENTS, &error))
    {
        fprintf (stderr, "Can't load config file %s: %s\n", 
                 tempstr, error->message);
        return -1;
    }

    gftp_config_register_items (gftp_global_config_items);

    for (i=0; gftp_protocols[i].register_options != NULL; i++) {
        if (gftp_protocols[i].register_options != NULL)
            gftp_protocols[i].register_options ();
    }

    return 0;
}

int
gftp_config_save () 
{
    FILE *fp;
    gchar *data;
    gsize length;
    ssize_t nwritten;

    fp = fopen (gftp_expand_path (CONFIG_FILE2), "w+");

    if (fp == NULL) {
        fprintf (stderr, "Can't save config file %s\n", CONFIG_FILE2);
        return -1;
    }

    data = g_key_file_to_data (key_file, &length, NULL);

    if (data == NULL)
        return -1;

    if ( (nwritten = fwrite (data, length, 1, fp)) <= 0) {
        perror ("saving configure file fails\n");
        return(-1);			/* error */
    }

    fclose (fp);

    return 0;
}


gchar* 
gftp_config_get_string (const char *group, const char *key)
{
    GError *error = NULL;
    gchar *r;

    r = g_key_file_get_string (key_file, group, key, &error);
    if (error != NULL) {
        g_warning ("Getting key %s of group %s fails: %s", key, group,
            error->message);
        return NULL;
    }

    return r;
}

void
gftp_config_set_string (const char *group, const char *key, const char *string)
{
    g_key_file_set_string (key_file, group, key, string);
}

gboolean
gftp_config_get_boolean (const char *group, const char *key)
{
    GError *error = NULL;
    gboolean r;

    r = g_key_file_get_boolean (key_file, group, key, &error);
    if (error != NULL) {
        g_warning ("Getting key %s of group %s fails: %s", key, group,
            error->message);
        return FALSE;
    }

    return r;
}


void
gftp_config_set_boolean (const char *group, const char *key, gboolean value)
{
    g_key_file_set_boolean (key_file, group, key, value);
}


gdouble
gftp_config_get_double (const char *group, const char *key)
{
    GError *error = NULL;
    gdouble r;

    r = g_key_file_get_double (key_file, group, key, &error);
    if (error != NULL) {
        g_warning ("Getting key %s of group %s fails: %s", key, group,
            error->message);
        return 0;
    }

    return r;
}

void
gftp_config_set_double (const char *group, const char *key, gdouble value)
{
    g_key_file_set_double (key_file, group, key, value);
}


int
gftp_config_get_integer (const char *group, const char *key)
{
    GError *error = NULL;
    int r;

    r = g_key_file_get_integer (key_file, group, key, &error);
    if (error != NULL) {
        g_warning ("Getting key %s of group %s fails: %s", key, group,
            error->message);
        return 0;
    }

    return r;
}

void
gftp_config_set_interger (const char *group, const char *key, int value)
{
    g_key_file_set_integer (key_file, group, key, value);
}
